package com.face.client.model;

import com.arcsoft.*;
import com.face.Const;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.PointerByReference;
import com.util.SDKUtils;

public class AFDEngine  implements FaceCheck, Engine {

    private final int size = 20 * 1024 * 1024;
    private final int nScale = 32;
    private final int faceNum = 1;

    private static ThreadLocal<Pointer> pEngine = new ThreadLocal<>();
    private static ThreadLocal<Pointer> pMemory = new ThreadLocal<>();

    public void release(Pointer engine) {
        AFD_FSDKLibrary.INSTANCE.AFD_FSDK_UninitialFaceEngine(engine);
    }

    //    sdk 方法
    public Pointer getFaceRes(ASVLOFFSCREEN inputImg) {
        PointerByReference ppFaceRes = new PointerByReference();
        NativeLong ret = AFD_FSDKLibrary.INSTANCE.AFD_FSDK_StillImageFaceDetection(get(), inputImg, ppFaceRes);
        if (ret.longValue() != 0) {
            throw new RuntimeException(String.format("AFD_FSDK_StillImageFaceDetection ret 0x%x", ret.longValue()));
        }
        return ppFaceRes.getValue();
    }

    @Override
    public FaceInfo[] getFaceInfo(ASVLOFFSCREEN asvloffscreen) {
        Pointer ppFaceRes = getFaceRes(asvloffscreen);
        AFD_FSDK_FACERES faceRes = new AFD_FSDK_FACERES(ppFaceRes);
        int num = faceRes.nFace;
        FaceInfo[] faceInfo = new FaceInfo[faceRes.nFace];
        for (int i = 0; i < num; i++) {
            MRECT rect = new MRECT(
                    new Pointer(Pointer.nativeValue(faceRes.rcFace.getPointer()) + faceRes.rcFace.size() * i));
            int orient = faceRes.lfaceOrient.getPointer().getInt(i * 4);
            faceInfo[i] = new FaceInfo();
            faceInfo[i].left = rect.left;
            faceInfo[i].top = rect.top;
            faceInfo[i].right = rect.right;
            faceInfo[i].bottom = rect.bottom;
            faceInfo[i].orient = orient;
        }
        return faceInfo;
    }


    @Override
    public Pointer get() {
        return get(pEngine);
    }

    @Override
    public Pointer init() {
        PointerByReference phFDEngine = new PointerByReference();
        System.out.println("初始化FD引擎");
        Pointer memory = SDKUtils.createMem(size);
        NativeLong ret = AFD_FSDKLibrary.INSTANCE.AFD_FSDK_InitialFaceEngine(Const.APPID,
                Const.FD_SDKKEY, memory ,
                size, phFDEngine, _AFD_FSDK_OrientPriority.AFD_FSDK_OPF_0_HIGHER_EXT, nScale, faceNum);
        if (ifError(memory, ret)) {
            System.err.println("FD引擎初始化异常");
        }
        Pointer engine = phFDEngine.getValue();
        pEngine.set(engine);
        pMemory.set(memory);
        return engine;
    }

    @Override
    public void destroy() {
        destroy(pEngine, pMemory);
    }
}
